package com.zhao.common.support;

import com.zhao.common.aop.Sign;
import com.zhao.common.util.RSAUtil;
import com.zhao.common.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;


@Slf4j
public class SignHandlerInterceptor implements HandlerInterceptor {

    private String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUY6fIbwdfniIU+CcEdqBBFKVQk/PQ/IlHwry9u1YHhiBd1YnO2NB7/cBiRSIHiymOPoH0Lv881EAJ0DtO/a9NoCxhsZfKSlBGkMmpTiq+ELrK7hC5GnNgkj0kY+NMTQwXZPz5qraIx1iXB6JL71R8YLsa7nu6L0c+66Wrm4DjZQIDAQAB";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod && ((HandlerMethod) handler).hasMethodAnnotation(Sign.class)) {
            String token = request.getHeader("Authorization");
            String[] split = token.split(" ");
            String tokenType = split[0];
            String tokenParams = split[1];
            String[] params = tokenParams.split(",");
            Map<String, Object> paramMap = new HashMap<>(10);
            for (String param : params) {
                log.info(param);
                String[] pars = param.split("=");
                paramMap.put(pars[0], pars[1].replace("\"", ""));
            }
            ConversionService conversionService = new DefaultConversionService();
            String mchId = conversionService.convert(paramMap.get("mchid"), String.class);
            String nonceStr = conversionService.convert(paramMap.get("nonce_str"), String.class);
            String signature = conversionService.convert(paramMap.get("signature"), String.class);
            Long timestamp = conversionService.convert(paramMap.get("timestamp"), Long.class);
            String serialNo = conversionService.convert(paramMap.get("serial_no"), String.class);
            String message = "";
            if ("GET".equals(request.getMethod())) {
                message = SignUtil.buildMessage(request.getMethod(), request.getRequestURI() + "?" + request.getQueryString(), timestamp, nonceStr, "");
            } else {
                BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
                String body = IOUtils.toString(reader);
                message = SignUtil.buildMessage(request.getMethod(), request.getRequestURI(), timestamp, nonceStr, body);
            }
            log.info(message);
            boolean isVerify = RSAUtil.verify(message, signature, RSAUtil.getPublicKey(publicKeyStr));
            log.info("preHandle {}", isVerify);
            return isVerify;
        } else {
            return true;
        }
    }

    public static void main(String[] args) throws Exception {
//        KeyPair keyPair = RSAUtil.generateKeyPair();
//        String publicKeyStr = RSAUtil.key2String(keyPair.getPublic());
//        String privateKeyStr = RSAUtil.key2String(keyPair.getPrivate());
//        System.out.println(privateKeyStr);
//        System.out.println(publicKeyStr);
//        String mchId = "1900009191";
//        String method = "GET";
//        String canonicalUrl = "/v1/account/getAccount/abc";
//        String body = "message";
//        String nonceStr = UUID.randomUUID().toString();
//        String serialNo = "";
//        long timestamp = System.currentTimeMillis();
//        String token = "WECHATPAY2-SHA256-RSA2048 " + SignUtil.getToken(method, canonicalUrl, timestamp, body, mchId, privateKeyStr, nonceStr, serialNo);
//        System.out.println(token);
//        String[] split = token.split(" ");
//        String tokenType = split[0];
//        String tokenParams = split[1];
//        String[] params = tokenParams.split(",");
//        Map<String, Object> paramMap = new HashMap<>(10);
//        for (String param : params) {
//            System.out.println(param);
//            String[] pars = param.split("=");
//            paramMap.put(pars[0], pars[1].replace("\"", ""));
//        }
//        ConversionService conversionService = DefaultConversionService.getSharedInstance();
//        String mchId1 = conversionService.convert(paramMap.get("mchid"), String.class);
//        String nonceStr1 = conversionService.convert(paramMap.get("nonce_str"), String.class);
//        String signature1 = conversionService.convert(paramMap.get("signature"), String.class);
//        Long timestamp1 = conversionService.convert(paramMap.get("timestamp"), Long.class);
//        String serialNo1 = conversionService.convert(paramMap.get("serial_no"), String.class);
//        String message1 = SignUtil.buildMessage(method, canonicalUrl, timestamp1, nonceStr1, body);
//        boolean isVerify = RSAUtil.verify(message1, signature1, RSAUtil.getPublicKey(publicKeyStr));
//        System.out.println(isVerify);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView
            modelAndView) throws Exception {
        log.info("postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion");
    }
}
